package com.zone.lib.download.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import com.zone.lib.download.db.DownloadDaoUtilsStore;
import com.zone.lib.download.enums.AppStatusEnum;
import com.zone.lib.download.bean.DownloadInfo;
import com.zone.lib.download.bean.RequestInfo;
import com.zone.lib.download.db.entity.Download;
import com.zone.lib.download.execute.DownloadExecutor;
import com.zone.lib.download.execute.DownloadTask;
import com.zone.lib.download.utils.AppStatusUpdateNotify;
import com.zone.lib.download.utils.LogUtils;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

public class DownloadService extends Service {

    public static final String TAG = DownloadService.class.getName();

    public static final String SERVICE_INTENT_EXTRA = "service_intent_extra";
    public static final String SERVICE_REFRESH_TASK = "service_refresh_task";
    public static final String SERVICE_DELETE_TASK = "service_delete_task";
    public static final String SERVICE_PAUSE_ALL_TASK = "service_pause_all_task";

    public static boolean canRequest = true;

    //关于线程池的一些配置
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = Math.max(3, CPU_COUNT/2);
    private static final int MAX_POOL_SIZE = CORE_POOL_SIZE * 2;
    private static final long KEEP_ALIVE_TIME  = 1000000L;

    private static final int MAX_RUNNING_TASK =  3;
    private DownloadExecutor mExecutor = new DownloadExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
            KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<Runnable>());

    //存储任务
    private final HashMap<String, DownloadTask> mTasks = new HashMap<>();

    public DownloadService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        synchronized (mTasks) {
//        if (canRequest){
            LogUtils.i(TAG, "onStartCommand() -> 启动了service服务 intent=" + intent + "\t this=" + this);
//            canRequest = false;
            try {
                if (null != intent && intent.hasExtra(SERVICE_INTENT_EXTRA)) {
                    ArrayList<RequestInfo> requesetes =
                            (ArrayList<RequestInfo>) intent.getSerializableExtra(SERVICE_INTENT_EXTRA);
                    if (null != requesetes && requesetes.size() > 0) {
                        for (RequestInfo request : requesetes) {
                            executeDownload(request);
                        }
                    }
                } else if (null != intent && intent.hasExtra(SERVICE_REFRESH_TASK)) {
                    freshTask();
                } else if (null != intent && intent.hasExtra(SERVICE_DELETE_TASK)) {
                    String code = intent.getStringExtra(SERVICE_DELETE_TASK);
                    if (StringUtils.isNotEmpty(code)) {
                        deleteTask(code);
                    }
                } else if (null != intent && intent.hasExtra(SERVICE_PAUSE_ALL_TASK)) {
                    pauseAllTask();
                }
            } catch (Exception e) {
                LogUtils.i(TAG, "onStartCommand()-> 接受数据,启动线程中发生异常");
                e.printStackTrace();
            }
        }
//            canRequest = true;
//        }
        return super.onStartCommand(intent, flags, startId);
    }

    //Todo  除了简单的synchronized, 是否有更好的方式来进行加锁呢
    private synchronized void executeDownload(RequestInfo requestInfo){
        Log.d(TAG, "executeDownload start");
        DownloadInfo mDownloadInfo = requestInfo.getDownloadInfo();
        if (ObjectUtils.isEmpty(mDownloadInfo)){
            Log.d(TAG, "DownloadInfo is null, this task break out !");
            return;
        }
        //先看看在任务列表里，是否有这个任务
        DownloadTask task = mTasks.get(mDownloadInfo.getCode());
        Download download = requestInfo.getDownloadInfo().getDownload();
//        Download download = DownloadDaoUtilsStore.getInstance().getDownloadByCode(mDownloadInfo.getCode());
        checkTask(mDownloadInfo, download);

        if (null == task){ //之前没有类似任务
            Log.d(TAG, "task is null");
            if (null != download){
                Log.d(TAG, "download is not null");
                if (mDownloadInfo.getAction() == AppStatusEnum.DOWNLOAD_PREPARE.CODE
                        && (download.getDownloadStatus() == AppStatusEnum.DOWNLOAD_PAUSE.CODE
                        || download.getDownloadStatus() == AppStatusEnum.DOWNLOAD_FAIL.CODE)){
                    //修正文件状态
                    download.setDownloadStatus(mDownloadInfo.getAction());
                    AppStatusUpdateNotify.appNotify(getApplicationContext(), download);
                }else if (download.getDownloadStatus() == AppStatusEnum.DOWNLOAD_COMPLETE.CODE){
                    Log.e(TAG, "this app " + download.getCode() +" is finish download ");
                    return;
                }
            }else {
                //创建下载记录
                Log.e(TAG, "download is null");
                return;
            }
            //创建一个下载任务
            task = new DownloadTask(getApplicationContext(), requestInfo);
            mTasks.put(mDownloadInfo.getCode(), task);
            if (mDownloadInfo.getAction() == AppStatusEnum.DOWNLOAD_WAIT.CODE){
                task.waiting();
                return;
            }else if (mDownloadInfo.getAction() == AppStatusEnum.DOWNLOAD_PAUSE.CODE){
                task.pause();
                return;
            }
        } else {
            Download download1 = task.getDownload();
            if (ObjectUtils.isNotEmpty(download1)){
                if (mDownloadInfo.getAction() != AppStatusEnum.DOWNLOAD_PAUSE.CODE &&
                        download1.getDownloadStatus() >= AppStatusEnum.INSTALL_SUCCESS.CODE){
                    task.cancel();
                    mTasks.remove(mDownloadInfo.getCode());
                    return;
                }else if (mDownloadInfo.getAction() == AppStatusEnum.DOWNLOAD_PAUSE.CODE){
                    task.pause();
                    return;
                }
                // 什么情况下, 可能存在这种这种状态
                if (mDownloadInfo.getAction() == AppStatusEnum.DOWNLOAD_PREPARE.CODE
                        && (task.getStatus() == AppStatusEnum.DOWNLOAD_WAIT.CODE
                        || task.getStatus() == AppStatusEnum.DOWNLOAD_PAUSE.CODE
                        || task.getStatus() == AppStatusEnum.DOWNLOAD_COMPLETE.CODE)){
                    task.restart();
                }else if (task.getStatus() == AppStatusEnum.DOWNLOAD_LOADING.CODE
                        || task.getStatus() == AppStatusEnum.DOWNLOAD_DELETE.CODE){
                    if (!mDownloadInfo.getFile().exists()){
                        task.cancel();
                        mTasks.remove(mDownloadInfo.getCode());
                        LogUtils.i(TAG, " 状态标示完成，但是文件不存在，重新执行下载文件 ");
                        return;
                    }
                }
            }
        }
        Log.d(TAG, "task is not null! action = "+requestInfo.getDownloadInfo().getAction());
        if (mDownloadInfo.getAction() == AppStatusEnum.DOWNLOAD_PREPARE.CODE
            || mDownloadInfo.getAction() == AppStatusEnum.UPDATE.CODE){
            mExecutor.executeTask(task);
        }
    }

    private void freshTask(){
        int doingTotal = 0;
        List<String> deleteList = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(mTasks)){
            Iterator<DownloadTask> downloadTaskIterator = mTasks.values().iterator();
            while (downloadTaskIterator.hasNext()) {
                DownloadTask downloadTask = downloadTaskIterator.next();
                Download download = downloadTask.getDownload();
                Download download1 = DownloadDaoUtilsStore.getInstance().getDownloadByCode(download.getCode());
                if (ObjectUtils.isEmpty(download1)){
                    deleteList.add(downloadTask.getDownLoadInfo().getCode());
                }else {
                    if (downloadTask.getStatus() == AppStatusEnum.DOWNLOAD_LOADING.CODE
                            || downloadTask.getStatus() == AppStatusEnum.DOWNLOAD_PREPARE.CODE){
                        doingTotal++;
                    } else if (downloadTask.getStatus() != AppStatusEnum.DOWNLOAD_WAIT.CODE
                            && downloadTask.getStatus() != AppStatusEnum.DOWNLOAD_PAUSE.CODE
                        ){
                        deleteList.add(downloadTask.getDownLoadInfo().getCode());
                    }
                }
            }
            for (int i = 0; i < deleteList.size(); i++) {
                String code = deleteList.get(i);
                DownloadTask downloadTask = mTasks.get(code);
                if (ObjectUtils.isNotEmpty(downloadTask)) {
                    downloadTask.cancel();
                    mTasks.remove(code);
                }
            }
            if (doingTotal < MAX_RUNNING_TASK){
                downloadTaskIterator = mTasks.values().iterator();
                while (downloadTaskIterator.hasNext()){
                    DownloadTask downloadTask = downloadTaskIterator.next();
//                    if (downloadTask.getStatus() == AppStatusEnum.DOWNLOAD_PAUSE.CODE){
//                        downloadTask.restart();
//                        mExecutor.executeTask(downloadTask);
//                    }else
                    if (downloadTask.getStatus() == AppStatusEnum.DOWNLOAD_WAIT.CODE){
                        mExecutor.executeTask(downloadTask);
                    }
                }
            }
        }
    }

    /**
     * 业务逻辑 只有三个task可以为执行状态，其余后来者全部等待状态
     * @param mDownloadInfo
     * @param download
     */
    private void checkTask(DownloadInfo mDownloadInfo, Download download) {
        int doingTotal = 0;
        if (ObjectUtils.isNotEmpty(mTasks)){
            Iterator<DownloadTask> downloadTaskIterator = mTasks.values().iterator();
            while (downloadTaskIterator.hasNext()){
                DownloadTask downloadTask = downloadTaskIterator.next();
                if (downloadTask.getStatus() == AppStatusEnum.DOWNLOAD_LOADING.CODE
                    || downloadTask.getStatus() == AppStatusEnum.DOWNLOAD_PREPARE.CODE){
                    doingTotal++;
                    if (doingTotal >= MAX_RUNNING_TASK){
                        mDownloadInfo.setAction(AppStatusEnum.DOWNLOAD_WAIT.CODE);
                        download.setDownloadStatus(AppStatusEnum.DOWNLOAD_WAIT.CODE);
                    }
                }
            }
        }
    }

    /**
     * 删除指定 task
     * @param code
     */
    private void deleteTask(String code){
        if (ObjectUtils.isNotEmpty(mTasks)){
            DownloadTask task = mTasks.get(code);
            if (ObjectUtils.isNotEmpty(task)){
                task.cancel();
                mTasks.remove(code);
            }
        }
    }

    /**
     * 暂停全部 task
     * @param
     */
    private void pauseAllTask(){
        if (ObjectUtils.isNotEmpty(mTasks)){
            Iterator<String> keys = mTasks.keySet().iterator();
            while (keys.hasNext()){
                String key = keys.next();
                DownloadTask task = mTasks.get(key);
                if (task.getStatus() == AppStatusEnum.DOWNLOAD_PREPARE.CODE
                        || task.getStatus() == AppStatusEnum.DOWNLOAD_LOADING.CODE
                        || task.getStatus() == AppStatusEnum.DOWNLOAD_WAIT.CODE
                    ){
                    task.pause();
                }
            }
        }
    }

}
